package com.example.mq.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.BusinessExceptionUtils;
import com.example.mq.mapper.SequentialMsgNumberGeneratorMapper;
import com.example.mq.po.SequentialMsgNumberGeneratorPO;
import com.example.mq.service.ISequentialMsgNumberGeneratorService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/*
@description:
@ClassName SequentialMsgNumberGeneratorServiceImpl
@author chen
@create 2025-08-25 19:39
@Version 1.0
*/
@Service
public class SequentialMsgNumberGeneratorServiceImpl extends ServiceImpl<SequentialMsgNumberGeneratorMapper, SequentialMsgNumberGeneratorPO> implements ISequentialMsgNumberGeneratorService
{
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long get(String groupId)
    {
        Objects.nonNull(groupId);
        SequentialMsgNumberGeneratorPO po = this.getAndInit(groupId);
        long value = po.getNumbering() + 1;
        po.setNumbering(value);
        boolean update = this.updateById(po);
        if (!update)
        {
            throw BusinessExceptionUtils.businessException("系统繁忙，请稍后重试");
        }
        return value;
    }


    private SequentialMsgNumberGeneratorPO getAndInit(String groupId)
    {
        LambdaQueryWrapper<SequentialMsgNumberGeneratorPO> qw =
                Wrappers.lambdaQuery(SequentialMsgNumberGeneratorPO.class)
                        .eq(SequentialMsgNumberGeneratorPO::getGroupId, groupId);
        SequentialMsgNumberGeneratorPO po = getOne(qw);
        if (po == null)
        {
            po = new SequentialMsgNumberGeneratorPO();
            po.setId(IdUtil.fastSimpleUUID());
            po.setGroupId(groupId);
            po.setNumbering(0L);
            po.setVersion(0L);
            this.save(po);
        }
        return po;
    }
}
